package danran.dbapi.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import danran.dbapi.common.ApiConfig;
import danran.dbapi.common.ApiSql;
import danran.dbapi.common.ResponseDto;
import danran.dbapi.domain.ApiDto;
import danran.dbapi.mapper.ApiConfigMapper;
import danran.dbapi.mapper.ApiSqlMapper;
import danran.dbapi.mapper.DataSourceMapper;
import danran.dbapi.plugin.CachePlugin;
import danran.dbapi.plugin.PluginManager;
import danran.dbapi.utils.TimeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Classname ApiConfigService
 * @Description TODO
 * @Date 2022/1/13 9:30
 * @Created by RanCoder
 */
@Service
public class ApiConfigService {
    private static Logger log = LoggerFactory.getLogger(ApiConfigService.class);
    @Autowired
    private ApiConfigMapper apiConfigMapper;
    @Autowired
    private DataSourceMapper dataSourceMapper;
    @Autowired
    private ApiSqlMapper apiSqlMapper;
    @Autowired
    private PluginService pluginService;

    /***
     * 添加api配置
     * @param apiConfig
     * @return
     */
    @Transactional
    public ResponseDto add(ApiConfig apiConfig) {
        if (apiConfigMapper.selectCountByPath(apiConfig.getPath()) == 0) {
            apiConfig.setStatus(0);
            apiConfig.setId(UUID.randomUUID().toString());
            String now = TimeUtil.now();
            apiConfig.setCreateTime(now);
            apiConfig.setUpdateTime(now);

            log.info("添加一个新的API:" + apiConfig.toString());
            apiConfigMapper.insert(apiConfig);

            apiConfig.getSqlList().forEach(sql -> {
                sql.setApiId(apiConfig.getId());
                apiSqlMapper.insert(sql);
            });
            // 修改插件使用信息
            pluginService.addPluginInUse(apiConfig.getCachePlugin(), apiConfig.getTransformPlugin());
            return ResponseDto.successWithMsg("成功添加一个API");
        } else {
            log.info("该API的路径已经被用了！");
            return ResponseDto.fail("该API的路径已经被用了！");
        }
    }

    public String getToken(String groupId) {
        return apiConfigMapper.getToken(groupId);
    }

    @Transactional
    public ResponseDto update(ApiConfig apiConfig) {
        Integer size = apiConfigMapper.selectCountByPathWhenUpdate(apiConfig.getPath(), apiConfig.getId());
        if (size > 0) {
            return ResponseDto.fail("API路径已经被使用,请勿重复更新");
        } else {
            ApiConfig old = apiConfigMapper.selectById(apiConfig.getId());
            apiConfig.setStatus(0);
            apiConfig.setUpdateTime(TimeUtil.now());
            apiConfigMapper.updateById(apiConfig);
            apiSqlMapper.deleteByApiID(apiConfig.getId());

            apiConfig.getSqlList().forEach(sql -> {
                sql.setApiId(apiConfig.getId());
                apiSqlMapper.insert(sql);
            });

            // 清空所有的缓存
            if (!apiConfig.getCachePlugin().equals("")) {
                try {
                    CachePlugin cachePlugin = PluginManager.getCachePlugin(old.getCachePlugin());
                    cachePlugin.clean(old);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return ResponseDto.successWithMsg("更新成功");
        }
    }

    @Transactional
    public void delete(String id, String path) {
        ApiConfig old = apiConfigMapper.selectById(id);
        // 删除api
        apiConfigMapper.deleteById(id);
        apiSqlMapper.deleteByApiID(id);
        pluginService.decrePluginInUse(old.getCachePlugin(), old.getTransformPlugin());

        if (old.getCachePlugin() == null) {
            return;
        }
        if (!"".equals(old.getCachePlugin())) {
            try {
                CachePlugin cachePlugin = PluginManager.getCachePlugin(old.getCachePlugin());
                cachePlugin.clean(old);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /***
     *
     * @param id apiconfig id
     * @return api config
     */
    public ApiConfig detail(String id) {
        ApiConfig apiConfig = apiConfigMapper.selectById(id);
        if (apiConfig == null) return apiConfig;
        List<ApiSql> apiSqls = apiSqlMapper.selectByApiId(apiConfig.getId());
        apiConfig.setSqlList(apiSqls);
        return apiConfig;
    }

    /***
     * 返回所有的apiconfig
     *
     * @return
     */
    public List<ApiConfig> getAll() {
        List<ApiConfig> apiConfigs = apiConfigMapper.selectList(null);
        return apiConfigs.stream()
                .sorted(Comparator.comparing(ApiConfig::getUpdateTime)
                        .reversed()).collect(Collectors.toList());
    }

    public JSONArray getAllDetail() {
        List<ApiDto> allDetail = apiConfigMapper.getAllDetail();
        Map<String, List<ApiDto>> map =
                allDetail.stream().collect(Collectors.groupingBy(ApiDto::getGroupName));
        JSONArray arr = new JSONArray();
        map.forEach((key, value) -> {
            JSONObject o = new JSONObject();
            o.put("name", key);
            o.put("children", value);
            arr.add(o);
        });
        return arr;
    }

    public List<ApiConfig> search(String keyword,
                                  String field,
                                  String groupId) {
        if (!"".equals(keyword)) {
            keyword = "%" + keyword + "%";
        }
        return apiConfigMapper.selectByKeyword(keyword, field, groupId);
    }

    /***
     * 获取在线的api信息
     * @param path
     * @return
     */
    public ApiConfig getConfig(String path) {
        log.info("=============getConfig=============");
        ApiConfig apiConfigOnline = apiConfigMapper.selectByPathOnline(path);
        if (apiConfigOnline == null) return null;
        List<ApiSql> apiSqls = apiSqlMapper.selectByApiId(apiConfigOnline.getId());
        apiConfigOnline.setSqlList(apiSqls);
        return apiConfigOnline;
    }

    /***
     * 上线api
     * @param id
     * @param path
     */
    public void online(String id, String path) {
        ApiConfig apiConfig = apiConfigMapper.selectById(id);
        apiConfig.setStatus(1);
        apiConfigMapper.updateById(apiConfig);
    }

    /***
     * api下线
     * @param id
     * @param path
     */
    public void offline(String id, String path) {
        ApiConfig apiConfig = apiConfigMapper.selectById(id);
        apiConfig.setStatus(0);
        apiConfigMapper.updateById(apiConfig);
        if (!"".equals(apiConfig.getCachePlugin())) {
            try {
                CachePlugin cachePlugin = PluginManager.getCachePlugin(apiConfig.getCachePlugin());
                cachePlugin.clean(apiConfig);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public String getPath(String id) {
        ApiConfig apiConfig = apiConfigMapper.selectById(id);
        return apiConfig == null ? null : apiConfig.getPath();
    }

    /***
     * 导出接口文档
     *
     * @param ids 需要导出的api的id列表
     * @return Markdown 字符串
     */
    public String apiDocs(List<String> ids) {
        StringBuffer temp = new StringBuffer("# 接口文档\n---\n");
        List<ApiConfig> list = apiConfigMapper.selectBatchIds(ids);
        list.forEach(t -> {
            temp.append("## ").append(t.getName()).append("\n- 接口地址： /api/").append(t.getPath())
                    .append("\n- 接口备注：").append(t.getNote()).append("\n- 请求参数：");

            String params = t.getParams();
            JSONArray array = JSON.parseArray(params);

            if (array.size() > 0) {
                StringBuilder buffer = new StringBuilder();
                buffer.append("\n\n| 参数名称 | 参数类型 | 参数说明 |\n");
                buffer.append("| :----: | :----: | :----: |\n");

                for (int i = 0; i < array.size(); i++) {
                    JSONObject jsonObject = array.getJSONObject(i);
                    String name = jsonObject.getString("name");
                    String type = jsonObject.getString("type");
                    if (type.startsWith("Array")) {
                        type = type.substring(6, type.length() - 1) + "数组";
                    }
                    String note = jsonObject.getString("note");
                    buffer.append("|").append(name).append("|").append(type).append("|").append(note).append("|\n");
                }

                temp.append(buffer);
            } else {
                temp.append("无参数\n");
            }
            temp.append("\n---\n");
        });

        temp.append("\n导出日期：").append(TimeUtil.now());
        return temp.toString();
    }

    public List<String> getAllIPIDs() {
        return apiConfigMapper.getAllIPIDs();
    }

    public List<ApiConfig> selectBatch(List<String> ids) {
        return apiConfigMapper.selectBatchIds(ids);
    }

    @Transactional
    public void insertBatch(List<ApiConfig> apiConfigs) {
        apiConfigs.forEach(a -> {
            String now = TimeUtil.now();
            a.setCreateTime(now);
            a.setUpdateTime(now);
            apiConfigMapper.insert(a);
        });
    }


}
